﻿namespace ReplayDataFile
{
    using System;
    using System.Collections.Generic;
    using System.Diagnostics;
    using System.IO;
    using System.Runtime.CompilerServices;
    using System.Runtime.InteropServices;

    public abstract class BlockDataBase
    {
        private List<BlockFile> bfFileList = new List<BlockFile>();
        private List<BlockFile> bfFreeFileList = new List<BlockFile>();
        protected string dataFilePath;

        public BlockDataBase(string filePath)
        {
            if (!string.IsNullOrEmpty(filePath))
            {
                this.dataFilePath = filePath.Trim();
            }
            this.IsOpened = false;
        }

        public virtual bool Close()
        {
            this.IsOpened = false;
            return true;
        }

        public ICollection<DataTypeInfo> GetDataAllTypes()
        {
            Dictionary<int, DataTypeInfo> dictionary = new Dictionary<int, DataTypeInfo>();
            foreach (BlockFile file in this.FileList)
            {
                foreach (DataTypeDirEntry entry in file.DataTypeDir.DirEntries)
                {
                    if (!dictionary.ContainsKey(entry.DataType))
                    {
                        DataTypeInfo info = new DataTypeInfo {
                            DataType = entry.DataType,
                            Name = entry.Name,
                            HasIndex = entry.IsWriteIndex
                        };
                        dictionary.Add(info.DataType, info);
                    }
                }
            }
            return dictionary.Values;
        }

        public void GetDataTimeRange(out DateTime beginTime, out DateTime endTime)
        {
            GetDataTimeRange(this.FileList, out beginTime, out endTime);
        }

        public static void GetDataTimeRange(List<BlockFile> bfileList, out DateTime beginTime, out DateTime endTime)
        {
            beginTime = DateTime.MaxValue;
            endTime = DateTime.MinValue;
            foreach (BlockFile file in bfileList)
            {
                DateTime time;
                DateTime time2;
                file.GetDataTimeRange(out time, out time2);
                if (time < beginTime)
                {
                    beginTime = time;
                }
                if (time2 > endTime)
                {
                    endTime = time2;
                }
            }
            if (beginTime == DateTime.MaxValue)
            {
                beginTime = DateTime.MinValue;
            }
        }

        public ICollection<DataTypeInfo> GetDataTypes(List<int> dataTypeList)
        {
            Dictionary<int, DataTypeInfo> dictionary = new Dictionary<int, DataTypeInfo>();
            foreach (BlockFile file in this.FileList)
            {
                foreach (int num in dataTypeList)
                {
                    List<DataTypeDirEntry> dirEntryList = file.DataTypeDir.GetDirEntryList(num);
                    foreach (DataTypeDirEntry entry in dirEntryList)
                    {
                        if (!dictionary.ContainsKey(entry.DataType))
                        {
                            DataTypeInfo info = new DataTypeInfo {
                                DataType = entry.DataType,
                                Name = entry.Name,
                                HasIndex = entry.IsWriteIndex
                            };
                            dictionary.Add(info.DataType, info);
                        }
                    }
                }
            }
            return dictionary.Values;
        }

        public ICollection<int> GetDataVersionList()
        {
            Dictionary<int, int> dictionary = new Dictionary<int, int>();
            foreach (BlockFile file in this.FileList)
            {
                foreach (DataTypeDirEntry entry in file.DataTypeDir.DirEntries)
                {
                    if (!IsInnerDataType(entry.DataType))
                    {
                        List<int> allocBlockList = file.BlockAllocTable.GetAllocBlockList(entry.FirstDataBlock);
                        foreach (int num in allocBlockList)
                        {
                            BlockInfo blockInfo = file.BlockAllocTable.GetBlockInfo(num);
                            if ((blockInfo.AllocFlag != -1) && !dictionary.ContainsKey(blockInfo.DataVersion))
                            {
                                dictionary.Add(blockInfo.DataVersion, blockInfo.DataVersion);
                            }
                        }
                    }
                }
            }
            return dictionary.Keys;
        }

        public DateTime GetLastDataTime()
        {
            if (this.IsOpened && (this.FileList.Count > 0))
            {
                BlockFile file = this.FileList[this.FileList.Count - 1];
                int count = file.Header.TimeSegments.Count;
                if (count > 0)
                {
                    return file.Header.TimeSegments[count - 1].EndTime;
                }
            }
            return DateTime.MinValue;
        }

        public List<TimeSegment> GetOverlappedTimeSegmentList()
        {
            throw new NotImplementedException();
        }

        private long GetTotalRecordCount()
        {
            long num = 0L;
            foreach (BlockFile file in this.FileList)
            {
                num += file.Header.RecordCount;
            }
            return num;
        }

        private static bool IsInnerDataType(int dataType)
        {
            return (dataType < 0);
        }

        public virtual bool Open()
        {
            bool flag = false;
            if (!Directory.Exists(this.dataFilePath))
            {
                if (!File.Exists(this.dataFilePath))
                {
                    return false;
                }
                flag = true;
            }
            DateTime now = DateTime.Now;
            SortedList<long, BlockFile> list = new SortedList<long, BlockFile>();
            string[] strArray = flag ? new string[] { this.dataFilePath } : Directory.GetFiles(this.dataFilePath);
            foreach (string str in strArray)
            {
                BlockFile item = new BlockFile(str);
                if (item.Open())
                {
                    item.Close();
                    long fileId = item.Header.FileId;
                    if (fileId == 0L)
                    {
                        this.FreeFileList.Add(item);
                    }
                    else if (list.ContainsKey(fileId))
                    {
                        Trace.WriteLine(string.Format("已经包含相同Id: {0} 的文件！", fileId));
                    }
                    else
                    {
                        list.Add(fileId, item);
                    }
                }
            }
            for (int i = 0; i < (list.Count - 1); i++)
            {
                long num3 = list.Keys[i];
                long num4 = list.Keys[i + 1];
                if ((num4 - num3) != 1L)
                {
                    Trace.WriteLine(string.Format("文件序号 {0}  {1} 不连续！", num3, num4));
                }
            }
            this.bfFileList.Clear();
            this.bfFileList.AddRange(list.Values);
            this.TotalRecordCount = this.GetTotalRecordCount();
            TimeSpan span = (TimeSpan) (DateTime.Now - now);
            this.IsOpened = true;
            return true;
        }

        public List<BlockFile> FileList
        {
            get
            {
                return this.bfFileList;
            }
        }

        public List<BlockFile> FreeFileList
        {
            get
            {
                return this.bfFreeFileList;
            }
        }

        public bool IsOpened { get; protected set; }

        public long TotalRecordCount { get; private set; }
    }
}

